package com.springboot.distributed.transaction;

import java.io.Serializable;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.AopUtils;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;

/**
 * 分布式事务拦截器
 *
 * @author supu
 * @date 2019-09-06 11:33
 **/
public class DistributedTransactionInterceptor extends TransactionInterceptor implements Serializable {
    private static final long serialVersionUID = 6933519854105360866L;

    private DistributedTransactionHandler distributedTransactionHandler;

    public DistributedTransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas,
                                             DistributedTransactionHandler distributedTransactionHandler) {
        super(ptm, tas);
        this.distributedTransactionHandler = distributedTransactionHandler;
    }

    @Override
    public Object invoke(final MethodInvocation invocation) throws Throwable {
        if(distributedTransactionHandler.isGlobalDistributedTransactionAnnotated(invocation.getMethod())){
            distributedTransactionHandler.registerDistributedTransaction();
        } else {
            Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
            if(targetClass != null ){
                logger.info("targetClass=" + targetClass + ", method=" + invocation.getMethod());
                try {
                    Method targetMethod = targetClass.getDeclaredMethod(invocation.getMethod().getName(), invocation.getMethod().getParameterTypes());
                    if(distributedTransactionHandler.isGlobalDistributedTransactionAnnotated(targetMethod)){
                        distributedTransactionHandler.registerDistributedTransaction();
                    }
                } catch (NoSuchMethodException | SecurityException e) {
                    logger.error("反射获取method异常", e);
                }
            }
        }
        return super.invoke(invocation);
    }
}
